{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'\\n均值滤波和高斯滤波都会在不同程度上模糊图像\\n中值滤波对椒盐噪声的滤波效果很好\\n'"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 1. 以Lena为原始图像，通过OpenCV实现平均滤波，高斯滤波及中值滤波，比较滤波结果\n",
    "import cv2\n",
    "import numpy as np\n",
    "from matplotlib import pyplot as plt\n",
    "import random\n",
    "\n",
    "def sp_noise(image,prob):\n",
    "    '''\n",
    "    添加椒盐噪声\n",
    "    prob:噪声比例 \n",
    "    '''\n",
    "    output = np.zeros(image.shape,np.uint8)\n",
    "    thres = 1 - prob \n",
    "    for i in range(image.shape[0]):\n",
    "        for j in range(image.shape[1]):\n",
    "            rdn = random.random()\n",
    "            if rdn < prob:\n",
    "                output[i][j] = 0\n",
    "            elif rdn > thres:\n",
    "                output[i][j] = 255\n",
    "            else:\n",
    "                output[i][j] = image[i][j]\n",
    "    return output\n",
    "\n",
    "def gasuss_noise(image, mean=0, var=0.001):\n",
    "    ''' \n",
    "        添加高斯噪声\n",
    "        mean : 均值 \n",
    "        var : 方差\n",
    "    '''\n",
    "    image = np.array(image/255, dtype=float)\n",
    "    noise = np.random.normal(mean, var ** 0.5, image.shape)\n",
    "    out = image + noise\n",
    "    if out.min() < 0:\n",
    "        low_clip = -1.\n",
    "    else:\n",
    "        low_clip = 0.\n",
    "    out = np.clip(out, low_clip, 1.0)\n",
    "    out = np.uint8(out*255)\n",
    "    #cv.imshow(\"gasuss\", out)\n",
    "    return out\n",
    "\n",
    "src = cv2.imread(\"lena.jpg\")\n",
    "\n",
    "# 为便于查看效果，向原图中人为添加噪声\n",
    "# 添加高斯噪声\n",
    "# src = gasuss_noise(src)\n",
    "# 添加椒盐噪声\n",
    "src = sp_noise(src, 0.1)\n",
    "\n",
    "blur_img = cv2.blur(src, (5, 5))\n",
    "gaussian_blur_img = cv2.GaussianBlur(src, (5, 5), 0)\n",
    "median_blur_img = cv2.medianBlur(src, 5)\n",
    "\n",
    "# 原图\n",
    "cv2.imshow(\"source\", src)\n",
    "cv2.waitKey(4000)\n",
    "# 均值滤波\n",
    "cv2.imshow(\"blur_img\", blur_img)\n",
    "cv2.waitKey(4000)\n",
    "# 高斯滤波\n",
    "cv2.imshow(\"gaussian_blur_img\", gaussian_blur_img)\n",
    "cv2.waitKey(4000)\n",
    "# 中值滤波\n",
    "cv2.imshow(\"median_blur_img\", median_blur_img)\n",
    "cv2.waitKey(4000)\n",
    "\n",
    "cv2.destroyAllWindows()\n",
    "\n",
    "'''\n",
    "均值滤波和高斯滤波都会在不同程度上模糊图像\n",
    "中值滤波对椒盐噪声的滤波效果很好\n",
    "'''"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'\\nSobel算子刻画的边缘较为粗糙\\nCanny算子刻画的边缘\\n'"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 以Lena为原始图像，通过OpenCV使用Sobel及Canny算子检测，比较边缘检测结果。 \n",
    "import cv2 as cv\n",
    "import numpy as np\n",
    "from matplotlib import pyplot as plt\n",
    "\n",
    "img = cv.imread(\"lena.jpg\", 0)\n",
    "\n",
    "sobelx = cv.Sobel(img, -1, 1, 0, ksize=5)\n",
    "sobely = cv.Sobel(img, -1, 0, 1, ksize=5)\n",
    "sobelxy = cv.Sobel(img, -1, 1, 1, ksize=5)\n",
    "laplacian = cv.Laplacian(img, -1, scale=1, delta=0)\n",
    "abs_sobelx = cv.convertScaleAbs(sobelx)\n",
    "abs_sobely = cv.convertScaleAbs(sobely)\n",
    "abs_sobelxy = cv.convertScaleAbs(sobelxy)\n",
    "abs_laplacian = cv.convertScaleAbs(laplacian)\n",
    "canny_img = cv.Canny(img, 50,200)\n",
    "\n",
    "cv.imshow(\"sobelx\", sobelx)\n",
    "cv.waitKey(4000)\n",
    "cv.imshow(\"sobely\", sobely)\n",
    "cv.waitKey(4000)\n",
    "cv.imshow(\"sobelxy\", sobelxy)\n",
    "cv.waitKey(4000)\n",
    "cv.imshow(\"abs_laplacian\", abs_laplacian)\n",
    "cv.waitKey(4000)\n",
    "cv.imshow(\"canny_img\", canny_img)\n",
    "cv.waitKey(40000)\n",
    "cv2.destroyAllWindows()\n",
    "\n",
    "'''\n",
    "Sobel算子刻画的边缘较为粗糙\n",
    "Canny算子检测准确，对噪声稳健，自动连接了细小的断裂边缘，能够很好的刻画目标边缘\n",
    "'''"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 3 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "'\\n对于前后背景区分较为明显的双峰图像，大津算法有较好的表现\\n'"
      ]
     },
     "execution_count": 39,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 3. 在OpenCV安装目录下找到课程对应演示图片(安装目录\\sources\\samples\\data)，首先计算灰度直方图，\n",
    "#    进一步使用大津算法进行分割，并比较分析分割结果。\n",
    "\n",
    "import cv2 as cv\n",
    "import numpy as np\n",
    "from matplotlib import pyplot as plt\n",
    "\n",
    "img = cv.imread(\"rice.png\", 0)\n",
    "img = cv2.medianBlur(img, 5)\n",
    "# 图像，通道[0]-灰度图，掩膜-无，灰度级，像素范围\n",
    "hist_cv = cv.calcHist(img, [0], None, [256], [0, 256])\n",
    "plt.subplot(131), plt.imshow(img, cmap='gray'), plt.title('source')\n",
    "plt.subplot(132),plt.plot(hist_cv), plt.title('histogram')\n",
    "\n",
    "# 大津算法做分割\n",
    "ret, otsu_img = cv.threshold(img, 0, 255, cv.THRESH_BINARY+cv.THRESH_OTSU)\n",
    "plt.subplot(133),plt.imshow(otsu_img, cmap='gray'), plt.title('otsu_img')\n",
    "plt.show()\n",
    "'''\n",
    "对于前后背景区分较为明显的双峰图像，大津算法有较好的表现\n",
    "'''"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "第1个米粒，中心点:(70.75001525878906, 242.25003051757812),宽高：(24.748737335205078,9.899495124816895)\n",
      "第2个米粒，中心点:(133.50001525878906, 243.50003051757812),宽高：(8.485280990600586,28.284271240234375)\n",
      "第3个米粒，中心点:(218.2200164794922, 241.4600067138672),宽高：(27.399999618530273,9.800000190734863)\n",
      "第4个米粒，中心点:(156.5159149169922, 234.9458465576172),宽高：(9.577043533325195,28.172468185424805)\n",
      "第5个米粒，中心点:(92.5, 221.5),宽高：(25.0,7.0)\n",
      "第6个米粒，中心点:(37.09247589111328, 225.50341796875),宽高：(10.014030456542969,29.462770462036133)\n",
      "第7个米粒，中心点:(188.3076934814453, 221.46153259277344),宽高：(9.984603881835938,28.289709091186523)\n",
      "第8个米粒，中心点:(53.95000076293945, 213.65000915527344),宽高：(22.76839828491211,7.905693531036377)\n",
      "第9个米粒，中心点:(138.20001220703125, 204.1000213623047),宽高：(9.838699340820312,26.385601043701172)\n",
      "第10个米粒，中心点:(72.75, 202.75003051757812),宽高：(9.899494171142578,28.991378784179688)\n",
      "第11个米粒，中心点:(107.72412872314453, 196.18968200683594),宽高：(8.356289863586426,28.225692749023438)\n",
      "第12个米粒，中心点:(216.60768127441406, 201.43846130371094),宽高：(27.18879508972168,9.296813011169434)\n",
      "第13个米粒，中心点:(202.7772216796875, 198.54666137695312),宽高：(29.368526458740234,9.61984634399414)\n",
      "第14个米粒，中心点:(41.749996185302734, 196.25003051757812),宽高：(28.991378784179688,9.899495124816895)\n",
      "第15个米粒，中心点:(94.83846282958984, 177.7923126220703),宽高：(9.302604675292969,25.427120208740234)\n",
      "第16个米粒，中心点:(170.32476806640625, 180.3556671142578),宽高：(9.23965072631836,28.531227111816406)\n",
      "第17个米粒，中心点:(27.500009536743164, 178.50001525878906),宽高：(28.284271240234375,9.899494171142578)\n",
      "第18个米粒，中心点:(183.20689392089844, 174.01724243164062),宽高：(9.284767150878906,25.440261840820312)\n",
      "第19个米粒，中心点:(143.4339599609375, 172.01885986328125),宽高：(9.615238189697266,28.845714569091797)\n",
      "第20个米粒，中心点:(61.25000762939453, 166.25),宽高：(8.485280990600586,28.991378784179688)\n",
      "第21个米粒，中心点:(116.25486755371094, 162.5778350830078),宽高：(8.79533863067627,27.134557723999023)\n",
      "第22个米粒，中心点:(198.076904296875, 158.11538696289062),宽高：(8.320503234863281,25.238859176635742)\n",
      "第23个米粒，中心点:(234.0, 148.5),宽高：(28.0,9.0)\n",
      "第24个米粒，中心点:(41.75000762939453, 148.25001525878906),宽高：(28.991378784179688,8.485280990600586)\n",
      "第25个米粒，中心点:(92.5, 147.5),宽高：(9.0,25.0)\n",
      "第26个米粒，中心点:(205.0384521484375, 142.69229125976562),宽高：(9.429903030395508,30.231159210205078)\n",
      "第27个米粒，中心点:(71.21154022216797, 136.5576934814453),宽高：(28.829071044921875,9.41357421875)\n",
      "第28个米粒，中心点:(63.11585235595703, 121.45731353759766),宽高：(8.613659858703613,24.40536880493164)\n",
      "第29个米粒，中心点:(154.70001220703125, 128.1000213623047),宽高：(29.068883895874023,9.391485214233398)\n",
      "第30个米粒，中心点:(39.0, 126.5),宽高：(8.0,27.0)\n",
      "第31个米粒，中心点:(208.00003051757812, 119.50001525878906),宽高：(23.33452033996582,10.60660171508789)\n",
      "第32个米粒，中心点:(132.22413635253906, 115.81034851074219),宽高：(9.979290962219238,27.83696937561035)\n",
      "第33个米粒，中心点:(109.5, 121.0),宽高：(9.0,26.0)\n",
      "第34个米粒，中心点:(20.911762237548828, 121.35295867919922),宽高：(27.891597747802734,8.731282234191895)\n",
      "第35个米粒，中心点:(178.88177490234375, 121.09334564208984),宽高：(13.0549955368042,56.403350830078125)\n",
      "第36个米粒，中心点:(65.9411849975586, 99.76472473144531),宽高：(27.163990020751953,8.731282234191895)\n",
      "第37个米粒，中心点:(20.25293731689453, 95.38823699951172),宽高：(8.973490715026855,26.92047119140625)\n",
      "第38个米粒，中心点:(88.5, 98.5),宽高：(9.0,27.0)\n",
      "第39个米粒，中心点:(208.19105529785156, 96.64966583251953),宽高：(29.52921485900879,10.2155122756958)\n",
      "第40个米粒，中心点:(156.0, 89.5),宽高：(28.991378784179688,9.192387580871582)\n",
      "第41个米粒，中心点:(116.81764221191406, 82.42941284179688),宽高：(26.573984146118164,9.65340518951416)\n",
      "第42个米粒，中心点:(58.5, 75.5),宽高：(37.0,25.0)\n",
      "第43个米粒，中心点:(182.0, 82.0),宽高：(22.0,40.0)\n",
      "第44个米粒，中心点:(27.5, 74.5),宽高：(9.0,29.0)\n",
      "第45个米粒，中心点:(94.45999145507812, 69.77999877929688),宽高：(28.60000228881836,8.600000381469727)\n",
      "第46个米粒，中心点:(147.78689575195312, 68.1557388305664),宽高：(8.781967163085938,28.156614303588867)\n",
      "第47个米粒，中心点:(160.8800048828125, 60.340003967285156),宽高：(9.40000057220459,29.200002670288086)\n",
      "第48个米粒，中心点:(130.1999969482422, 60.600006103515625),宽高：(8.22192096710205,28.46049690246582)\n",
      "第49个米粒，中心点:(64.31999969482422, 54.2400016784668),宽高：(20.400001525878906,10.0)\n",
      "第50个米粒，中心点:(208.2260284423828, 55.102745056152344),宽高：(8.544004440307617,24.929765701293945)\n",
      "第51个米粒，中心点:(90.90000915527344, 49.20000457763672),宽高：(9.391485214233398,25.043960571289062)\n",
      "第52个米粒，中心点:(35.42129898071289, 53.408870697021484),宽高：(14.138827323913574,47.61104202270508)\n",
      "第53个米粒，中心点:(103.16216278076172, 39.02702713012695),宽高：(9.86393928527832,26.96143341064453)\n",
      "第54个米粒，中心点:(184.1923065185547, 45.961544036865234),宽高：(25.887325286865234,23.533931732177734)\n",
      "第55个米粒，中心点:(68.46720886230469, 35.139347076416016),宽高：(8.834545135498047,20.613937377929688)\n",
      "第56个米粒，中心点:(229.96109008789062, 48.04619216918945),宽高：(53.342498779296875,23.91353988647461)\n",
      "第57个米粒，中心点:(216.32681274414062, 32.14146041870117),宽高：(26.121295928955078,8.939908027648926)\n",
      "第58个米粒，中心点:(154.9002685546875, 33.420989990234375),宽高：(43.263858795166016,18.781604766845703)\n",
      "第59个米粒，中心点:(23.299999237060547, 24.90000343322754),宽高：(10.28591251373291,27.280027389526367)\n",
      "第60个米粒，中心点:(42.60000228881836, 18.700000762939453),宽高：(9.391485214233398,25.043960571289062)\n",
      "第61个米粒，中心点:(127.5, 19.0),宽高：(8.877545356750488,26.468236923217773)\n",
      "第62个米粒，中心点:(113.51724243164062, 14.206899642944336),宽高：(20.42648696899414,8.170595169067383)\n",
      "第63个米粒，中心点:(91.80734252929688, 14.142203330993652),宽高：(26.81913948059082,9.290915489196777)\n",
      "一共有63米粒，米粒平均面积：220.38095238095238，米粒平均长度：28.745595932006836，米粒面积的方差：5890.997732426304，米粒长度的方差：41.50191932542195\n"
     ]
    }
   ],
   "source": [
    "# 4. 使用米粒图像，分割得到各米粒，首先计算各区域(米粒)的面积、长度等信息，进一步计算面积、长度\n",
    "#   的均值及方差，分析落在3sigma范围内米粒的数量\n",
    "import cv2 as cv\n",
    "import numpy as np\n",
    "from matplotlib import pyplot as plt\n",
    "\n",
    "img = cv.imread(\"rice.png\")\n",
    "img = cv.medianBlur(img, 5)\n",
    "cv.imshow(\"source\",img)\n",
    "cv.waitKey(1000)\n",
    "\n",
    "# 利用canny算子求取边缘\n",
    "canny_img = cv.Canny(img, 100, 200)\n",
    "cv.imshow(\"canny\",canny_img)\n",
    "cv.waitKey(1000)\n",
    "\n",
    "# 寻找轮廓\n",
    "#h = cv.findContours(canny_img, cv.RETR_TREE, cv.CHAIN_APPROX_NONE)\n",
    "h = cv.findContours(canny_img, cv.RETR_EXTERNAL,cv.CHAIN_APPROX_SIMPLE)\n",
    "contours = h[1]\n",
    "#画出轮廓：temp是白色幕布，contours是轮廓，-1表示全画，然后是颜色，厚度\n",
    "img1 = img.copy()\n",
    "cv.drawContours(img1, contours, -1, (0,0,255), 1)\n",
    "# 计算各个米粒的面积 计算各个米粒的长度\n",
    "count=0 #米粒总数\n",
    "rice_ares = []\n",
    "rice_length = []\n",
    "for cont in contours:\n",
    "    ares = cv.contourArea(cont)#计算包围性状的面积\n",
    "    if ares<50:   #过滤面积小于10的形状\n",
    "        continue\n",
    "    count+=1    #总体计数加1\n",
    "    rice_ares.append(ares)\n",
    "    #rect = cv.boundingRect(cont) #提取矩形坐标    \n",
    "    #print(\"第{}个米粒，x:{} y:{} w:{} h{}\".format(count, rect[0],rect[1], rect[2], rect[3]))#打印坐标\n",
    "    rect = cv.minAreaRect(cont) #提取最小包围矩形\n",
    "    print(\"第{}个米粒，中心点:{},宽高：({},{})\".format(count, rect[0], rect[1][0], rect[1][1]))#打印坐标     \n",
    "    if rect[1][0] > rect[1][1]:        \n",
    "        rice_length.append(rect[1][0])\n",
    "    else:        \n",
    "        rice_length.append(rect[1][1])\n",
    "\n",
    "print(\"一共有{}米粒，米粒平均面积：{}，米粒平均长度：{}，米粒面积的方差：{}，米粒长度的方差：{}\"\\\n",
    "      .format(count, np.mean(rice_ares), np.mean(rice_length), np.var(rice_ares), np.var(rice_length)))\n",
    "cv.imshow(\"contour_img\",img1)\n",
    "cv.waitKey(10000)\n",
    "# 求取米粒长度的均值及方差\n",
    "\n",
    "cv.destroyAllWindows()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "# 5. 使用棋盘格及自选风景图像，分别使用SIFT、FAST及ORB算子检测角点，并比较分析检测结果。\n",
    "import cv2\n",
    "import numpy as np\n",
    "from matplotlib import pyplot as plt\n",
    "\n",
    "img = cv2.imread(\"chessboard_copy.png\")\n",
    "img = cv2.medianBlur(img, 5)\n",
    "cv2.namedWindow(\"source\", cv2.WINDOW_NORMAL);\n",
    "cv2.imshow(\"source\",img)\n",
    "\n",
    "gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)\n",
    "\n",
    "# Harris检测角点\n",
    "float_img = np.float32(gray)\n",
    "# 输入图像必须是 float32，最后一个参数在 0.04 到 0.05 之间\n",
    "dst = cv2.cornerHarris(float_img,2,3,0.04)\n",
    "dst = cv2.dilate(dst,None)\n",
    "img1 = img.copy()\n",
    "img1[dst>0.01*dst.max()]=[0,0,255]\n",
    "cv2.namedWindow(\"Harris\", cv2.WINDOW_NORMAL);\n",
    "cv2.imshow('Harris',img1)\n",
    "\n",
    "# SIFT检测角点\n",
    "sift = cv2.xfeatures2d.SIFT_create()\n",
    "kp = sift.detect(gray,None)\n",
    "img2 = gray.copy()\n",
    "img2=cv2.drawKeypoints(img2, kp, img2)\n",
    "cv2.namedWindow(\"SIFT\", cv2.WINDOW_NORMAL);\n",
    "cv2.imshow('SIFT',img2)\n",
    "\n",
    "# FAST检测角点\n",
    "fast = cv2.FastFeatureDetector_create(threshold=20,nonmaxSuppression=True,type=cv2.FAST_FEATURE_DETECTOR_TYPE_9_16)\n",
    "kp = fast.detect(gray,None)\n",
    "img3 = gray.copy()\n",
    "img3=cv2.drawKeypoints(img3, kp, img3)\n",
    "cv2.namedWindow(\"FAST\", cv2.WINDOW_NORMAL);\n",
    "cv2.imshow('FAST',img3)\n",
    "\n",
    "# ORB检测角点\n",
    "orb = cv2.ORB_create()\n",
    "kp = orb.detect(gray,None)\n",
    "img4 = gray.copy()\n",
    "img4=cv2.drawKeypoints(img4, kp, img4)\n",
    "cv2.namedWindow(\"ORB\", cv2.WINDOW_NORMAL);\n",
    "cv2.imshow('ORB',img4)\n",
    "\n",
    "cv2.waitKey(20000)\n",
    "cv2.destroyAllWindows()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
